;------------------------------------------------------ ; ; Monitor multi-firmware per start-up ; computer Z80 Nuova Elettronica ; ; Copyright Roberto Bazzano 2006 - 2022 ; ;------------------------------------------------------ ; ; BANCHI 2 e 3 - Allocati da F800h a FFFFh ; ; NOTA: durante tutto il codice il registro B' contiene 00h se c'è la scheda video vecchia. Se non c'è contiene FFh ; Il registro C' contiene il numero della pagina di menù visualizzata a video ; ;------------------------------------------------------ ; .org 00000h ; solo per debug con simulatore ;------------------------------------------------------ #define version "1.3" ; versione programma #define anno "2022" ; anno finale del copyright banco .equ 05fh ; porta di I/O per la selezione del banco di memoria della EPROM lf060 .equ 0f060h ; routine f060h della eprom 2390 (carica in R14, R15, R18 e R19 l'indirizzo (HL) del cursore e del carattere da visualizzare) lf06e .equ 0f06eh ; routine f06eh della eprom 2390 (carica in R18 e R19 l'indirizzo (HL) del carattere da visualizzare) lf0a5 .equ 0f0a5h ; routine f0a5h della eprom 2390 (inizializza i registri del SY6545 ed i PIO) .org 0f800h ; JUMP table jp start ; F800h inizio firmware jp input ; F803h routine input da tastiere jp video ; F806h routine output video start: di ; disabilita gli interrupt ld hl,045edh ; inizializza il vettore per l'NMI ld (0066h),hl ; mettendo l'istruzione RETN (ED 45) xor a ; spegne il motore del floppy out (0d6h),a ld hl,0ebffh ; cerca dove posizionare lo SP prima di EC00 sp1: ld a,(hl) cpl ld (hl),a cp (hl) jr z,sp3 sp2: dec hl jr sp1 sp3: cpl ld (hl),a cp (hl) jr nz,sp2 ld sp,hl ld a,01h ; seleziona il banco della 2390. ATTENZIONE: questo banco deve rimanere sempre selezionato fino all'uscita del firmware, serve per l'output sul video nuovo out (banco),a call lf0a5 ; inizializza i registri del SY6545 ed i PIO call checv ; imposta il registro B' che indica se esiste la scheda video vecchia tast0: ld hl,out0 ; visualizza il messaggio "SELECT" sui display call msg call vmenu1 ; pulisce i video e visualizza il menù tast0a: call input ; input da tastiere cp 10h jr z,tast0d ; se è stato premuto CR salta subito al controllo del tasto jr nc,tast0a ; se è maggiore di F looppa cp 01h jr c,tast0a ; se è minore di 1 looppa ld hl,curs ; calcola la posizione sul video vecchio per visualizzare il numero digitato call vloc ; calcola in DE l'indirizzo del video in base alla riga/colonna nella locazione puntata da HL e HL+1 push af ; visualizza il numero digitato cp 0Ah jr nc,tast0b ; se A >= 0ah addiziona 037h, altrimenti 030h add a,030h jr tast0c tast0b: add a,037h tast0c: ld (de),a ; sul video vecchio call writen ; e sul video nuovo - Il cursore è già posizionato pop af tast0d: ld hl,tabtas ; calcola il puntatore alla tabella di jump in HL dec a ; decrementa A, lo moltiplica per 2 e lo addiziona ad HL sla a ld c,a xor a ld b,a add hl,bc ; HL ora punta all'indirizzo da richiamare che è presente nella tabella "tabtas" ld c,(hl) ; carica il contenuto dell'indirizzo puntato da HL in BC inc hl ld b,(hl) push bc ; sposta BC su HL pop hl jp (hl) ; salta alla routine "tastX" calcolata tast1: ; se 1 lancia il boot del basic da 5.5 K ld hl,out10 ; messaggio da visualizzare sul display call disp ; visualizza il messaggio sui display e inizializza i video ld a,19h ; seleziona il banco del basic da 5.5 K su floppy out (banco),a jp 0f000h tast2: ; se 2 lancia il boot vecchio ld hl,out1 ; messaggio da visualizzare sul display call disp ; visualizza il messaggio sui display e inizializza i video ld a,00h ; seleziona il banco della 1390 out (banco),a jp 0f000h tast3: ; se 3 lancia il boot grafic ld hl,out2 ; messaggio da visualizzare sul display call disp ; visualizza il messaggio sui display e inizializza i video ld a,01h ; seleziona il banco della 2390 out (banco),a jp 0f000h tast4: ; se 4 lancia il boot del S.O.N.E. ld hl,out11 ; messaggio da visualizzare sul display call disp ; visualizza il messaggio sui display e inizializza i video ld a,1Ah ; seleziona il banco del s.o.n.e. out (banco),a jp 0f000h tast5: ; se 5 lancia il basic in rom rilocato in ram ld hl,out3 ; messaggio da visualizzare sul display call disp ; visualizza il messaggio sui display e inizializza i video ld a,08h ; seleziona il primo banco del basic in rom ld de,00000h tast5a: call setban ; sposta gli 8 banchi da 2K in ram inc a inc a cp 18h jr nz,tast5a jp 0000h ; salta al basic tast6: ; se 6 lancia il monitor esadecimale originale non rilocato call disp1 ; non visualizza alcun messaggio sui display e inizializza i video ld a,04h ; seleziona il banco del monitor esadecimale originale ld de,08000h ; seleziona il banco indicato da A e lo sposta in ram call setban jp 8000h tast7: ; se 7 lancia il monitor esadecimale non rilocato con lo SP rilocato prima di EC00 con il firmware non rilocato per il programmatore di eprom call disp1 ; non visualizza alcun messaggio sui display e inizializza i video ld a,20h ; seleziona il banco del monitor esadecimale con SP rilocato ld de,08000h ; seleziona il banco indicato da A e lo sposta in ram call setban jp 8000h tast8: ; se 8 lancia il monitor esadecimale rilocato con lo SP rilocato prima di EC00 per la tastiera alfanumerica con il firmware rilocato per il programmatore di eprom ld hl,out4 ; messaggio da visualizzare sul display call disp ; visualizza il messaggio sui display e inizializza i video ld a,1Ch ; seleziona il banco del monitor esadecimale rilocato per la tastiera alfanumerica out (banco),a jp 0f000h tast9: ; se 9 lancia il monitor esadecimale rilocato con lo SP rilocato prima di EC00 per la tastiera esadecimale con il firmware rilocato per il programmatore di eprom call disp1 ; non visualizza alcun messaggio sui display e inizializza i video ld a,1Eh ; seleziona il banco del monitor esadecimale rilocato per la tastiera esadecimale out (banco),a jp 0f000h tastA: ; se A lancia direttamente il bootstrap multiplo ld hl,out7 ; messaggio da visualizzare sul display call disp ; visualizza il messaggio sui display e inizializza i video ld a,06h ; seleziona il banco della 2390 modificata per non fare il check sul disco di boot out (banco),a jp 0f17dh ; salta direttamente al BOOT tastB: ; se B lancia il loader del basic da 5.5 K call disp1 ; non visualizza alcun messaggio sui display e inizializza i video ld a,04h ; seleziona il banco del monitor esadecimale originale ld de,08000h ; seleziona il banco indicato da A e lo sposta in ram call setban ld a,18h ; seleziona il banco del loader del basic da 5.5 K su cassetta ld de,00000h ; seleziona il banco indicato da A e lo sposta in ram call setban jp 0069h ; salta al loader tastC: ; se C lancia la prova tastiera ld hl,out8 ; messaggio da visualizzare sul display call disp ; visualizza il messaggio sui display e inizializza i video jp key tastD: ; se D salta a 0000h ld hl,out9 ; messaggio da visualizzare sul display call disp ; visualizza il messaggio sui display e inizializza i video jp 0000h tastE: ; se E salta a 1000h senza modificare i display ed i monitor jp 01000h tastF: ; se F sposta le routines di stampa per monitor esadecimale a 0070 ld a,07h ; seleziona il banco delle routines di stampa ld de,00070h ; seleziona il banco indicato da A e lo sposta in ram call setban ld a,01h ; seleziona il banco della 2390 out (banco),a jp tast0 tast10: ; se RETURN cambia pagina di menù exx ; carica il numero di pagina visualizzata in A ld a,c exx cp 01h ; confronta il valore di A con 1 call z,vmenu2 ; pulisce i video visualizza la pagina di menù appropriata call nz,vmenu1 jp tast0a ;------------------------------------------------------ ; visualizza il messaggio sui display, spegne il cursore sul video nuovo e inizializza i video ; Se HL=0 non visualizza il messaggio sui display ; Sporca AF disp: call msg ; Visualizza il messaggio indicato da HL sui display disp1: ld a,20h ; Spegne il cursore sul video nuovo call cursor disp2: call initv ; Inizializza il video vecchio call initn ; Inizializza il video nuovo ret ;------------------------------------------------------ ; Seleziona il banco indicato da A e lo sposta all'indirizzo indicato da DE ; Sporca tutti i registri setban: out (banco),a ; seleziona il banco ld hl,0f000h ; sposta il banco in ram ld bc,0800h ldir ret ;------------------------------------------------------ ; controlla se la scheda video vecchia è presente. Per farlo verifica il cambiamento della ritraccia video ; se la scheda video vecchia esiste ritorna 00h in B' ; se la scheda video vecchia non esiste ritorna FFh in B' checv: push af push hl exx ; mette 00h in B' ld b,00h exx ld hl,00000h ; inizializza il contatore checv1: inc hl ; attende al massimo fino a che HL non diventa 1000h ld a,h ; Infatti la ritraccia a "1" come tempo resta al massimo con HL a 0111h cp 10h ; Se impiega più tempo significa che la scheda LX.388 non è presente jr nz,checv2 exx ; se la LX.388 non è presente carica FF in B' ed esce ld b,0ffh exx jr checv3 checv2: in a,(0ebh) ; attende la ritraccia video bit 7,a jr nz,checv1 checv3: pop hl pop af ret ;------------------------------------------------------ ; controlla se è stata rilevata la scheda video vecchia ; ritorna Z a 0 se non c'è, Z a 1 se c'è chect: exx ; recupera il valore dal registro B' ld a,b exx or a ; imposta il flag Z ret ;------------------------------------------------------ ; pulizia del video vecchio initv: push hl push de push bc ld hl,0ec00h ld de,0ec01h ld (hl),20h ld bc,01ffh call waitv ; attende la ritraccia ldir pop bc pop de pop hl ret ;------------------------------------------------------ ; attende la ritraccia del video vecchio waitv: push af call chect ; esce se non esiste la scheda video vecchia jr nz,waitv2 waitv1: in a,(0ebh) ; attende la ritraccia video bit 7,a jr nz,waitv1 waitv2: pop af ret ;------------------------------------------------------ ; pulizia del video nuovo initn: push af push hl ld hl,0h initn1: call lf06e ; carica in R18 e R19 l'indirizzo (HL) del carattere da visualizzare ld a,20h ; imposta il carattere a "blank" call writen ; scrive il carattere inc hl ld a,l cp 81h jr nz,initn1 ld a,h cp 07h jr nz,initn1 pop hl pop af ret ;------------------------------------------------------ ; accende o spegne il cursore sul video nuovo ; A=00h accende, A=20h spegne cursor: push af ld a,0ah ; seleziona il registro R10 out (8ch),a pop af ; scrive il valore 32 (20h) per spegnere il cursore out (8dh),a ret ;------------------------------------------------------ ; Subroutine per la visualizzazione del menù sui video ; vmenu1: ld hl,menu1 ; visualizza la 1° pagina del menu exx ; carica in C' il numero della pagina visualizzata ld c,01h exx jr vis vmenu2: ld hl,menu2 ; visualizza la 2° pagina del menu exx ; carica in C' il numero della pagina visualizzata ld c,02h exx vis: call disp1 ; pulisce i video push af vis1: push hl call nloc ; calcola in DE l'indirizzo del video nuovo in base alla riga/colonna nella locazione puntata da HL e HL+1 push de pop hl call lf06e ; carica in R18 e R19 l'indirizzo (HL) del carattere da visualizzare pop hl call vloc ; calcola in DE l'indirizzo del video vecchio in base alla riga/colonna nella locazione puntata da HL e HL+1 vis2: ld a,(hl) ; recupera il carattere da scrivere call waitv ; attende la ritraccia del video vecchio ld (de),a ; visualizza il carattere sul video vecchio inc de call writen ; attende la ritraccia e visualizza il carattere sul video nuovo inc hl xor a ; controlla se il prossimo carattere è 00h cp (hl) jr nz,vis2 inc hl cpl ; controlla se il prossimo carattere è 0ffh cp (hl) ; se no, ricarica la successiva prima posizione e looppa jr nz,vis1 ld hl,curs ; calcola in DE l'indirizzo del cursore in base alla riga/colonna nella locazione puntata da HL e HL+1 call nloc push de pop hl call lf060 ; carica in R14, R15, R18 e R19 l'indirizzo (HL) del cursore e del carattere da visualizzare xor a ; accende il cursore sul video nuovo call cursor pop af ret ;------------------------------------------------------ ; scrive il carattere presente in A sul video nuovo writen: call waitn ; attende la ritraccia out (80h),a ; scrive il carattere push af ld a,1fh ; imposta gli attributi del carattere out (8eh),a ld a,31 ; update out (8ch),a xor a out (8dh),a pop af ret ;------------------------------------------------------ ; attende la ritraccia del video nuovo waitn: push af waitn1: in a,(8ch) bit 7,a jr z,waitn1 pop af ret ;------------------------------------------------------ ; Calcola la locazione del video in base alla riga/colonna nella locazione puntata da HL e HL+1 ; Chiamare "vloc" per il video vecchio, "nloc" per il video nuovo ; Ritorna DE. HL punterà al primo carattere da visualizzare vloc: push af ld b,00h ld c,(hl) push hl ld hl,0ec00h ld de,00020h jr loc1 nloc: push af ld b,00h ld c,(hl) push hl ld hl,00158h ; offset per centrare la videata sul video nuovo da 80x24 ld de,00050h loc1: ld a,c or a ; cp 00h jr z,loc2 add hl,de dec c jr loc1 loc2: ex de,hl pop hl inc hl ld c,(hl) ex de,hl add hl,bc ex de,hl inc hl pop af ret ;------------------------------------------------------ ; Visualizza il messaggio puntato da HL sui display della tastiera esadecimale msg: push af push bc ld bc,08F7h msg1: ld a,(hl) out (c),a inc hl dec c dec b xor a cp b jr nz,msg1 pop bc pop af ret ;------------------------------------------------------ ; ROUTINE PER LA PROVA TASTIERA key: call initv ld bc,0020h iniz: ld hl,0ec00h in a,(0eah) ; input da tastiera vecchia call keyvis in a,(085h) ; input da tastiera nuova call keyvis in a,(085h) ; input da tastiera nuova complementato cpl call keyvis jr iniz keyvis: call key1 ; visualizza il dato come arriva da tastiera add hl,bc ; si posiziona sulla riga successiva and 7fh ; visualizza il dato con lo strobe a 0 call key1 add hl,bc ; si posiziona due righe dopo add hl,bc ret key1: push hl push af push af loop: pop af rlca jr c,uno call waitv ld (hl),'0' jr cont uno: call waitv ld (hl),'1' cont: push af inc hl ld a,l and 0fh cp 08h jr nz,loop pop af call sep ; separatore pop af ; visualizza il byte push af rra rra rra rra and 0fh call lett ; somma l'offset per l'ASCII del numero o della lettera call waitv ld (hl),a inc hl pop af push af and 0fh call lett call waitv ld (hl),a call sep ; separatore pop af ; visualizza il carattere ASCII call waitv ld (hl),a pop hl ret sep: inc hl ; separatore inc hl call waitv ld (hl),'-' inc hl inc hl ret lett: cp 0Ah jr c,lett1 ; salta se minore add a,55 ret lett1: add a,'0' ret ;------------------------------------------------------ menu1: .byte 000h, 006h, "Z80 NUOVA ELETTRONICA", 00h .byte 001h, 008h, "BOOTSTRAP V. ", version, 00h .byte 001h, 01dh, "1/2", 00h .byte 003h, 000h, "1 > BOOT BASIC 5.5K SU " .byte "FLOPPY", 00h .byte 004h, 000h, "2 > BOOT NE-DOS 1.5", 00h .byte 005h, 000h, "3 > BOOT NE-DOS GRAFIC 1.0", 00h .byte 006h, 000h, "4 > BOOT S.O.N.E.", 00h .byte 007h, 000h, "5 > BASIC 16K IN RAM", 00h .byte 008h, 000h, "6 > MONITOR ORIGINALE " .byte "NO INTERR.", 00h .byte 009h, 000h, "7 > MONITOR SP RILOC. " .byte "NO INTERR.", 00h .byte 00Ah, 000h, "8 > MONITOR A VIDEO " .byte "(RILOCATO)", 00h .byte 00Bh, 000h, "CR> CAMBIA PAGINA", 00h .byte 00Dh, 00Fh, "> <", 00h .byte 00Fh, 000h, "(C) ROBERTO BAZZANO " .byte "2000-" , anno, 00h .byte 0ffh menu2: .byte 000h, 006h, "Z80 NUOVA ELETTRONICA", 00h .byte 001h, 008h, "BOOTSTRAP V. ", version, 00h .byte 001h, 01dh, "2/2", 00h .byte 003h, 000h, "9 > MONITOR ORIGINALE " .byte "(RILOCATO)", 00h .byte 004h, 000h, "A > BOOT IMMEDIATO NE-DOS", 00h .byte 005h, 000h, "B > LOADER BASIC 5.5K SU " .byte "CASS.", 00h .byte 006h, 000h, "C > PROVA TASTIERA", 00h .byte 007h, 000h, "D > RESTART A 0000H", 00h .byte 008h, 000h, "E > RESTART A 1000H", 00h .byte 009h, 000h, "F > LOAD ROUTINES STAMPA " .byte "A 0070H", 00h .byte 00Bh, 000h, "CR> CAMBIA PAGINA", 00h .byte 00Dh, 00Fh, "> <", 00h .byte 00Fh, 000h, "(C) ROBERTO BAZZANO " .byte "2000-", anno, 00h .byte 0ffh curs: .byte 00Dh, 010h ; riga/colonna in cui posizionare il cursore ; Tabelle per visualizzazione su display tastiera esadecimale ; ; ; Valori per l'accensione dei segmenti del display: ; ; 1 ; - bit a 1 spegne il segmento ; 32 | | 2 ; - 64 F0 = display a destra ; 16 | | 4 !! ; - F7 = display a sinistra ; 8 ; 128 = punto decimale out0: .byte 0ffh, 092h, 086h, 0C7h, 086h, 0C6h, 087h, 0ffh ; select out1: .byte 0ABh, 086h, 0A1h, 0C0h, 092h, 0FFh, 079h, 092h ; nedos 1.5 out2: .byte 0ABh, 086h, 0A1h, 0C0h, 092h, 0FFh, 042h, 0F9h ; nedos G.1 out3: .byte 083h, 088h, 092h, 0F9h, 0C6h, 0FFh, 0F9h, 082h ; basic 16 out4: .byte 0C8h, 0C0h, 0ABh, 0F9h, 087h, 0C0h, 0AFh, 0FFh ; monitor out7: .byte 0FFh, 0FFh, 083h, 0C0h, 0C0h, 087h, 0FFh, 0FFh ; boot out8: .byte 0FFh, 0FFh, 087h, 086h, 092h, 087h, 0FFh, 0FFh ; test out9: .byte 0FFh, 0FFh, 0C1h, 092h, 086h, 0AFh, 0FFh, 0FFh ; user out10: .byte 083h, 088h, 092h, 0F9h, 0C6h, 0FFh, 012h, 092h ; basic 5.5 out11: .byte 0FFh, 0FFh, 092h, 0C0h, 0ABh, 086h, 0FFh, 0FFh ; sone ;------------------------------------------------------ ; ; Nuova routine di input tastiera per il monitor esadecimale ; Sostituisce la 80AA e accetta l'input dalla tastiera alfanumerica vecchia o nuova ; o dalla tastiera esadecimale convertendo il valore ricevuto in modo da essere ; compatibile con la 80AA ; ; Dati ricevuti dalla tastiera: ; Numeri da 0 a 9: da 30h a 39h ; Lettere da A ad F: da 61h a 66h ; Shift+numero da 1 a 9: da 21h a 29h ; Shift+lettere da A ad F: da 41h a 46h ; Return: 0dh input: push bc push de push hl t1: call chect ; Se non c'è la scheda video vecchia salta il controllo e passa subito alla tastiera nuova jr nz,t2 t1x: in a,(0eah) ; tastiera vecchia bit 7,a jr nz,t1x t2: in a,(085h) ; tastiera nuova bit 7,a jr z,t2 t2es1: ld hl,0456h ; tastiera esadecimale t2es2: in a,(0f0h) bit 7,a jr z,t2es1 t2es3: dec hl ld a,h or l jr nz,t2es2 ; Input da tastiere t2a: call chect ; Se non c'è la scheda video vecchia salta il controllo e passa subito alla tastiera nuova jr nz,t2ax in a,(0eah) ; tastiera vecchia bit 7,a jr nz,t2b t2ax: in a,(085h) ; tastiera nuova cpl bit 7,a jr nz,t2b in a,(0f0h) ; tastiera esadecimale bit 7,a jr z,tes4 jr t2a ; se non ho premuto nulla sulle tre tastiere allora looppa ; Input da tastiera esadecimale tes1: ld hl,0456h tes2: in a,(0f0h) bit 7,a jr z,tes1 tes3: dec hl ld a,h or l jr nz,tes2 tes4: in a,(0f0h) bit 7,a jr nz,tes4 ld b,a ld hl,0005h call rit tes5: in a,(0f0h) ld c,a and 7fh cp b jr nz,tes5 bit 7,c jr nz,tes1 tes6: jr texit ; Conversione dato per tastiere alfanumeriche t2b: and 7fh cp 0dh ; controlla se è stato premuto Return jr nz,t3 ld a,10h ; se si carica il valore di Control+0 jr texit t3: cp 03ah ; controlla se è stato premuto un numero jr nc,t4 cp 030h jr c,t4 sub 030h ; se si sottrae 30h ed esce jr texit t4: cp 67h ; controlla se è stata premuta una lettera tra A ed F jr nc,t5 cp 61h jr c,t5 sub 57h ; se si sottrae 57h ed esce jr texit t5: cp 2ah ; controlla se è stato premuto shift+numero (escluso 0) jr nc,t6 cp 21h jr c,t6 sub 10h ; se si sottrae 10h ed esce jr texit t6: cp 47h ; controlla se è stato premuto shift+lettera da A ad F jr nc,t7 cp 41h jr c,t7 sub 27h ; se si sottrae 27h ed esce jr texit t7: jp t1 texit: pop hl pop de pop bc ret ; Genera un ritardo rit: push hl push af rit1: call rit2 dec hl ld a,h or l jr nz,rit1 pop af pop hl ret rit2: push af push de ld de,0047h rit3: dec de ld a,d or e jr nz,rit3 pop de pop af ret ;------------------------------------------------------ ; ; Nuova routine di output su video per monitor esadecimale ; Sostituisce la 80EC e accetta l'input dalle locazioni da 0000h a 0007h ; convertendo il valore letto in modo da essere compatibile con la 80EC ; video: push af push bc push de push hl call chect ; esce se non esiste la scheda video vecchia jr nz,m3 m1: ld de,0007h ld bc,0ec00h m2: ld hl,tabout push bc ld a,(de) ld b,0h ld c,a add hl,bc pop bc ld a,(hl) call waitv ; attende la ritraccia video ld (bc),a dec e inc c ld a,e cp 0ffh jr nz,m2 m3: pop hl pop de pop bc pop af ret tabout: .byte "0123456789ABCDEF" .byte "-", " ", "M", "R", "#", "H", "L", "P", "C", "G" .byte "NQRTUVJY S" ;------------------------------------------------------ ; Jump table per il richiamo della routine di gestione della voce di menu selezionata tabtas: .dw tast1 .dw tast2 .dw tast3 .dw tast4 .dw tast5 .dw tast6 .dw tast7 .dw tast8 .dw tast9 .dw tastA .dw tastB .dw tastC .dw tastD .dw tastE .dw tastF .dw tast10 ;------------------------------------------------------ .org 0ffffh .byte 00h .end